package de.bazinga.rotw.weapon.grenade;

import java.util.Vector;

import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jmex.game.state.GameStateManager;
import com.jmex.jbullet.nodes.PhysicsNode;

import de.bazinga.rotw.base.attacker.AttackerList;
import de.bazinga.rotw.base.attacker.BaseAttacker;
import de.bazinga.rotw.collision.CollidableObjects;
import de.bazinga.rotw.effects.Explosion;
import de.bazinga.rotw.game.RotwGameState;
import de.bazinga.rotw.network.BasicSyncManager;
import de.bazinga.rotw.network.Client;
import de.bazinga.rotw.network.Server;
import de.bazinga.rotw.network.message.HitMessage;
import de.bazinga.rotw.network.message.NewBulletMessage;
import de.bazinga.rotw.network.message.physics.AppliedForceMessage;
import de.bazinga.rotw.person.OpponentList;
import de.bazinga.rotw.person.Person;
import de.bazinga.rotw.player.Player;
import de.bazinga.rotw.sound.Sound;
import de.bazinga.rotw.vehicle.Car;
import de.bazinga.rotw.vehicle.Vehicle;

public class HEGrenade extends Grenade {
	
	@SuppressWarnings("unchecked")
	public void handleCollision(Person person, Node rootNode, Vector3f location) {
		// Smoke Granade Test
		Explosion explosion = Explosion.getUnusedExplosion(location);
		rootNode.attachChild(explosion);
		explosion.getExplosionParticles().forceRespawn();
		
		explosion.hide();
		

		Player player = ((RotwGameState)GameStateManager.getInstance().getChild("gameState")).getPlayer();
		
		//if(person.getLocalTranslation().distance(player.getLocalTranslation()) < 40f) {
			Sound.getInstance().getAudioTrack("sounds/grenade.wav").play();
		//}
		
		
		BasicSyncManager syncManager = ((RotwGameState)GameStateManager.getInstance().getChild("gameState")).getSyncManager();
		if(syncManager instanceof Server) {
			
			Vector<Person> persons = new Vector<Person>();
			persons.addAll(OpponentList.getInstance().getOpponents().values());
			persons.add(player);
			
			for(Person p:persons) {
				int damage = 0;
				if(p.getLocalTranslation().distance(location) < 1) {
					damage = 60;
				}else if(p.getLocalTranslation().distance(location) < 3) {
					damage = 40;
				}else if(p.getLocalTranslation().distance(location) < 5) {
					damage = 20;
				}else if(p.getLocalTranslation().distance(location) < 9) {
					damage = 10;
				}
				
				if(damage > 0) {
					
					damage *= person.getDamageFactor();
					
					if(person.isDoubleDamage()) damage *= 2;
					
					if(p == person) {
						p.hit(person.getPlayerName(), damage, person.getCameraPosition());
					}else{
						p.hit(person, damage);
					}
					HitMessage hitMessage = new HitMessage();
					hitMessage.setPlayerName(person.getPlayerName());
					hitMessage.setPlayerLocation(person.getCameraPosition());
					hitMessage.setDamage(damage);
					hitMessage.setWeaponFlag(NewBulletMessage.HEGRANADE);
					((Server) syncManager).getServer().sendToPlayer(hitMessage, p.getPlayerId());
					
				}
			}
			
			
			// Check Vehicle
			Vector<Spatial> vehicles = CollidableObjects.getInstance().getObjects("vehicle");
			if(vehicles != null) {
				for(Spatial vec:vehicles) {
					Vehicle vehicle = (Vehicle)vec;
					float distance = vehicle.getLocalTranslation().distance(location);
					int damage = 0;
					
					if(distance < 5) damage = 51;
					else if(distance < 8) damage = 30;
					else if(distance < 10) damage = 20;
					
					if(damage > 0 && vehicle.getDamage() <= 100) {
						vehicle.setDamage(vehicle.getDamage() + damage, true);

						if(vehicle instanceof Car) {
							Vector3f force = ((Car)vehicle).getPhysicsCar().getLocalTranslation().subtract(location).normalize().divide(distance).mult(damage * 20);
							((Car)vehicle).getPhysicsCar()
								.applyImpulse(force, Vector3f.ZERO);
							


							int index = CollidableObjects.getInstance().getObjects("vehicle").indexOf(vec);
							// Send message
							AppliedForceMessage afm = new AppliedForceMessage();
							afm.setPhysicsIndex(index);
							afm.setForce(force);
							afm.setType(AppliedForceMessage.CAR);
							
							if(syncManager instanceof Server) {
								((Server)syncManager).getServer().sendToAll(afm);
							}else{
								((Client)syncManager).getClient().sendToServer(afm);
							}
						}
					}
				}
			}
			
			Vector<BaseAttacker> baseAttacters = (Vector<BaseAttacker>)AttackerList.getAttackers().clone();
			if(baseAttacters != null) {
				for(Spatial att:baseAttacters) {
					BaseAttacker attacker = (BaseAttacker)att;
					float distance = att.getLocalTranslation().distance(location);
					int damage = 0;
					
					if(distance < 5) damage = 100;
					else if(distance < 8) damage = 80;
					else if(distance < 10) damage = 40;
					
					damage *= person.getDamageFactor();
					
					if(person.isDoubleDamage()) damage *= 2;
					
					if(damage > 0) 
						attacker.hit(person, damage);
				}
			}
			
			// Check Physics-Objects
			Vector<Spatial> obj = CollidableObjects.getInstance().getObjects("physics");
			if(obj != null) {
				for(Spatial vec:obj) {
					float distance = vec.getLocalTranslation().distance(location);
					if(distance < 2) 
						distance = 2;
					if(vec instanceof PhysicsNode &&
							distance < 15) {
						Vector3f force = ((PhysicsNode)vec).getLocalTranslation().subtract(location).normalize().divide(distance).mult(100);
						((PhysicsNode)vec)
							.applyImpulse(force, Vector3f.ZERO);
						

						int index = CollidableObjects.getInstance().getObjects("physics").indexOf(vec);
						// Send message
						AppliedForceMessage afm = new AppliedForceMessage();
						afm.setPhysicsIndex(index);
						afm.setForce(force);
						
						if(syncManager instanceof Server) {
							((Server)syncManager).getServer().sendToAll(afm);
						}else{
							((Client)syncManager).getClient().sendToServer(afm);
						}
					}
				}
			}
		}
	}

	public int getWeaponFlag() {
		return NewBulletMessage.HEGRANADE;
	}
	

	// We dont need this
	public boolean reload() {
		return false;
	}
}